#pragma once
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DEV "/dev/null" // 数据黑洞，向它写入的数据会被丢弃，读取数据什么都读不到（不会使进程退出）
void DaemonSele(const char *currrPath = nullptr)
{
    // 1、让调用进程屏蔽异常的信号
    // SIGPIPE信号会在进程向一个已经关闭的socket连接写数据时产生，如果不处理这个信号，进程会被强制退出。通过忽略SIGPIPE信号，可以避免进程因为这个信号而退出。
    signal(SIGPIPE, SIG_IGN);
    // 2、让自己不是组长，调用setsid
    if (fork() > 0)
        exit(0);
    // 子进程——守护进程也称精灵进程，本质就是一个孤儿进程
    pid_t n = setsid();//进程不是组长的时候才能调用setsid，但是调用完之后，进程成为了组长
    assert(n != -1); // 失败返回-1
    // 3、守护进程脱离终端，所以要关闭或重定向进程默认打开的文件及文件描述符
    int fd = open(DEV, O_RDWR); // 以读写的方式打开文件黑洞
    if (fd >= 0)                // 创建成功：重定向
    {
        dup2(fd, 0); // 将fd覆盖标准输入
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }
    else // 创建失败：手动关闭文件描述符
    {
        close(0);
        close(1);
        close(2);
    }
    // 4、进程执行路径更改（可改可不改）
    if (currrPath)
    {
        chdir(currrPath);
    }
}